home *** CD-ROM | disk | FTP | other *** search
/ Young Minds / Young Minds Interactive CD-ROM.ISO / sdi / intersec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-18  |  5.2 KB  |  215 lines

  1. /************************************  intersect.c  ******************/
  2. #include "sdi.h"
  3.  
  4. /*
  5.  * Copyright 1987 by Mark Weiser.
  6.  * Permission to reproduce and use in any manner whatsoever on Suns is granted
  7.  * so long as this copyright and other identifying marks of authorship
  8.  * in the code and the game remain intact and visible.  Use of this code
  9.  * in other products is reserved to me--I'm working on Mac and IBM versions.
  10.  */
  11.  
  12. /*
  13.  * The code to intersect blasts, missiles, and lasers is in here,
  14.  * as well as some blast-specific code.
  15.  */
  16.  
  17. #define LINE_GRAIN 20
  18.  
  19. /* each 'line' is the head of a linked list of current blasts */
  20. static struct blast *lines_launch[MAX_LINES/LINE_GRAIN + 1], *lines_city[MAX_LINES/LINE_GRAIN + 1];
  21. static struct blast **init_line_from_bid(), **init_line_from_mid();
  22.  
  23. /*
  24.  * Clear out data structures which keep track of blasts. 
  25.  */
  26. init_intersect()
  27. {
  28.     int i;
  29.     for (i=0; i<(MAX_LINES/LINE_GRAIN +1); i++) {
  30.         lines_launch[i] = NULL;
  31.         lines_city[i] = NULL;
  32.     }
  33. }
  34.  
  35. /*
  36.  * Register a blast for later display.  After this call the blast will
  37.  * automatically be incremented and decremented in size, and will be checked
  38.  * for intersection with missiles.
  39.  */
  40. add_blast(bid)
  41. register struct blast *bid;
  42. {
  43.     /* for now don't sort, just stick at the head */
  44.     register int pos = bid->orig_y / LINE_GRAIN;
  45.     struct blast **lines;
  46.     if (pos < 0 || pos >= MAX_LINES/LINE_GRAIN + 1) {
  47.         return;
  48.     }
  49.     lines = init_line_from_bid(bid);
  50.     bid->next = lines[pos];
  51.     lines[pos] = bid;
  52.     blast_count++;        
  53. }
  54.  
  55. /*
  56.  * Remove a blast from the display list.  The blast will no longer
  57.  * intersect missiles, change in size, or be displayed. The blast must
  58.  * have already been cleared from the display elsewhere. The storage
  59.  * is not freed here, in case the blast is statically allocated.
  60.  */
  61. remove_blast(bid)
  62. register struct blast *bid;
  63. {    
  64.     struct blast **lines = init_line_from_bid(bid);
  65.     register struct blast *ptr = lines[bid->orig_y / LINE_GRAIN];
  66.     if (ptr == bid) {
  67.         /* head is special case */
  68.         lines[bid->orig_y / LINE_GRAIN] = bid->next;
  69.     } else {
  70.         while ( ptr != NULL && ptr->next != bid ) 
  71.             ptr = ptr->next;
  72.         if (ptr != NULL) 
  73.             ptr->next = bid->next;
  74.     }
  75.     blast_count--;
  76. }
  77.  
  78. /*
  79.  * See if the missile 'mid' has run into any blasts.
  80.  */
  81. intersect(mid)
  82. struct missile *mid;
  83. {
  84.     int start = max((mid->y - (MAX_CIRCLE >> 1) - 1) / LINE_GRAIN, 0);
  85.     int end = min((mid->y + (MAX_CIRCLE >> 1) + 1) / LINE_GRAIN, max_y);
  86.     register int i;
  87.     register struct blast *ptr;
  88.     struct blast **lines = init_line_from_mid(mid);
  89.     for (i=start; i <= end; i++) {
  90.         ptr = lines[i];
  91.         while (ptr != NULL) {
  92.             if (single_intersect(ptr, mid))
  93.                 return TRUE;
  94.             ptr = ptr->next;
  95.         }
  96.     }
  97.     return FALSE;
  98. }
  99.  
  100. /*
  101.  * See if the missile 'mid' is passing through blast 'bid'.  This routine
  102.  * is also used for laser initialization, with a fake 'bid' to simulate
  103.  * the laser range.  For purposes of computing intersection, the circular
  104.  * blast is considerd to be a rectangle with the same center and approximately
  105.  * the same area.  An intersection has occured if the missile passed
  106.  * through the blast between its last update and now, even if both endpoints
  107.  * are outside the blast.
  108.  */
  109. single_intersect(bid,mid)
  110. struct missile *mid;
  111. struct blast *bid;
  112. {
  113.     int x0 = mid->old_x, y0 = mid->old_y, x1 = mid->x, y1 = mid->y;
  114.     return rect_clipvector(&bid->r, &x0, &y0, &x1, &y1);
  115. }
  116.  
  117. /*
  118.  * Procedure 'func' is called for every blast on the display lists.
  119.  */
  120. doto_blasts(func)
  121. int (*func)();
  122. {
  123.     int i;
  124.     struct blast *bid, *next;
  125.     struct blast **lines;
  126.     lines = lines_launch;
  127.     for (i=0; i< (MAX_LINES/LINE_GRAIN + 1); i++) {
  128.         bid = lines[i];
  129.         while (bid != NULL) {
  130.             next = bid->next; /* in case func destroys it */
  131.             (*func)(bid);
  132.             bid = next;
  133.         }
  134.     }
  135.     lines = lines_city;
  136.     for (i=0; i<(MAX_LINES/LINE_GRAIN + 1); i++) {
  137.         bid = lines[i];
  138.         while (bid != NULL) {
  139.             next = bid->next; /* in case func destroys it */
  140.             (*func)(bid);
  141.             bid = next;
  142.         }
  143.     }
  144. }
  145.  
  146. /*
  147.  * Given a blast, return the proper display on which it will be found.
  148.  */
  149. static struct blast **
  150. init_line_from_bid(bid)
  151. struct blast *bid;
  152. {
  153.     if (bid->pw == launchpw) {
  154.         return lines_launch;
  155.     } else {
  156.         return lines_city;
  157.     }
  158. }
  159.  
  160. /*
  161.  * Given a missile, return the proper display list on which intersecting
  162.  * blasts will be found.
  163.  */
  164. static struct blast **
  165. init_line_from_mid(mid)
  166. struct missile *mid;
  167. {
  168.     if (mid->pw == launchpw) {
  169.         return lines_launch;
  170.     } else {
  171.         return lines_city;
  172.     }
  173. }
  174.  
  175. /*
  176.  * Remove all blasts from the display lists and free their storage.
  177.  * Nothing is done here about getting them off the display.
  178.  */
  179. static struct blast **line_list[] = {lines_launch, lines_city};
  180. free_all_blasts()
  181. {
  182.     int i, l;
  183.     struct blast *bid, *nextbid, **lines;
  184.     for (l=0; l < 2; l++) {
  185.         lines = line_list[l];
  186.             for (i=0; i<(MAX_LINES/LINE_GRAIN + 1); i++) {
  187.             bid = lines[i];
  188.             lines[i] = NULL;
  189.             while (bid != NULL) {
  190.                 nextbid = bid->next;
  191.                 free(bid);
  192.                 bid = nextbid;
  193.             }
  194.         }
  195.     }
  196.     blast_count = 0;
  197. }
  198.  
  199. /*
  200.     This is the old style, now commented out.  It would let a fast
  201.     moving missile pass right through, but did consider blasts to 
  202.     be real circles.
  203.  
  204. single_intersect(bid, mid)
  205. struct blast *bid;
  206. struct missile *mid;
  207. {
  208.     register short offx = B_WIDTH(bid)/2;
  209.     register short x = bid->x - mid->x;
  210.     register short y = bid->y - mid->y;
  211.     return (x*x + y*y) < (offx*offx);
  212. }
  213. */
  214.  
  215.